package me.keiwu.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Charsets;
import me.keiwu.pub.data.ConfigType;
import me.keiwu.pub.data.ResponseV2;
import me.keiwu.pub.data.config.ExploreConfigBean;
import me.keiwu.pub.data.enums.NoticeType;
import me.keiwu.pub.data.service.UserInfoBean;
import me.keiwu.pub.service.WXService;
import me.keiwu.pub.util.CacheUtil;
import me.keiwu.pub.util.DateUtil;
import me.keiwu.user.dao.CommentDao;
import me.keiwu.user.dao.CommentDetailDao;
import me.keiwu.user.domain.Comment;
import me.keiwu.user.domain.CommentDetail;
import me.keiwu.user.domain.UserForm;
import me.keiwu.user.service.CommentService;
import me.keiwu.user.service.NoticeService;
import me.keiwu.user.service.UserService;
import me.keiwu.user.service.UserStatisticsService;
import me.keiwu.user.util.ExceptionUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by kei on 02/02/2018.
 */
@Service
@Transactional
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentDao commentDao;
    @Autowired
    private CommentDetailDao commentDetailDao;
    @Autowired
    private UserStatisticsService userStatisticsService;
    @Autowired
    private UserService userService;
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private CacheUtil cacheUtil;

    @Autowired
    private WXService wxService;

    @Autowired
    private ExceptionUtil exceptionUtil;

    private static final Logger logger = LoggerFactory.getLogger(CommentServiceImpl.class);

    @Override
    public Page<Comment> list(Long userId, int page, int size) {
        Specification<Comment> spec = (root, query, cb) -> {
            Predicate p1 = cb.equal(root.get("owner"), userId);
            Predicate p2 = cb.equal(root.get("commenter"), userId);
            return cb.or(p1, p2);
        };
        Sort sort = new Sort(Sort.Direction.DESC, "time");
        Pageable pageable = new PageRequest(page, size, sort);
        return commentDao.findAll(spec, pageable);
    }


    @Override
    public Page<CommentDetail> detail(Long commentId, int page, int size) {
        Specification<CommentDetail> spec = (root, query, cb) -> {
            return cb.equal(root.get("commentId"), commentId);
        };
        Sort sort = new Sort(Sort.Direction.DESC, "time");
        Pageable pageable = new PageRequest(page, size, sort);
        return commentDetailDao.findAll(spec, pageable);
    }


    @Override
    public ResponseV2 comment(Long owner, Long commenter, String message) {
        // 先检查是否有未读消息，如果有，就不再发通知
        boolean skipTemplateMsg = noticeService.checkNotRead(NoticeType.COMMENT.getType(), owner);

        int now = DateUtil.getUnixTime();
        Comment c = commentDao.findByOwnerAndCommenter(owner, commenter);
        if (c == null) c = new Comment();
        if (!c.isPaid()) {
            ExploreConfigBean config = cacheUtil.getConfig(ConfigType.EXPLORE_CONFIG, ExploreConfigBean.class);
            if (config == null) return null;
            if (!userService.changeGold(commenter, config.getFirstCommentCost())) return ResponseV2.fail("星币不足");
            c.setPaid(true);
        }

        UserInfoBean cUser = userService.getUserInfo(commenter);
        c.setOwner(owner);
        c.setCommenter(commenter);
        c.setLastMsg(message);
        c.setTime(now);
        c.setAvatar(cUser.getWxAvatarUrl());
        c.setNickName(cUser.getNickName());
        commentDao.save(c);

        CommentDetail cd = new CommentDetail();
        cd .setCommentId(c.getId());
        cd.setAuthor(commenter);
        cd.setMsg(message);
        cd.setTime(now);
        commentDetailDao.save(cd);
        userStatisticsService.incrCommentCount(commenter);

        // 通知
        String simpleMsg = StringUtils.substring(message, 0, 50);
        JSONObject json = new JSONObject();
        json.put("commentId", c.getId());
        json.put("message", simpleMsg);
        String addition = json.toJSONString();
        noticeService.uniqueNotice(NoticeType.COMMENT, commenter, owner, addition, true);

        if(!skipTemplateMsg && isTimeForTmpMsg()){
            // TODO 发送模板消息
            UserInfoBean toUser = userService.getUserInfo(owner);
            if (toUser != null && cUser != null){
                UserForm userForm = userService.getOldestUserFormById(owner);
                if (userForm != null) {
                    boolean challengePoint = noticeService.checkNotRead(NoticeType.CHALLENGE.getType(), owner);
                    boolean stealPoint = noticeService.checkNotRead(NoticeType.STEAL_GOLD.getType(), owner);
                    boolean cmtPoint = noticeService.checkNotRead(NoticeType.STEAL_GOLD.getType(), owner);
                    boolean isRedPoint = challengePoint || stealPoint || cmtPoint;
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("formId", userForm.getFormId());
                    map.put("templateMsgType",4);
                    // 调用发送模板 传参发送消息
                    StringBuilder sbPage = new StringBuilder("pages/notification/notification?isRedPoint=");
                    sbPage.append(isRedPoint);
                    sbPage.append("&challengePoint=");
                    sbPage.append(challengePoint);
                    sbPage.append("&commentPoint=");
                    sbPage.append(cmtPoint);
                    sbPage.append("&stealGoldPoint=");
                    sbPage.append(stealPoint);
                    sbPage.append("&focus=0");
                    String page = sbPage.toString();
//                    String page = "https://filef05c93e60ef9.aiwall.com/v3/idea/YJLKY6pE";
                    exceptionUtil.logError(this.getClass(), "commentTmpMsg", "params:" + map.toString());
                    exceptionUtil.logError(this.getClass(), "commentTmpMsg", "page:" + page);
                    ResponseV2 resp = wxService.sendTemplateMsg(JSONObject.toJSONString(cUser), JSONObject.toJSONString(toUser), page, map);
                    if (resp.getCode() == HttpStatus.OK.value() || resp.getCode() == 1) {
                        userService.deleteUsedForm(userForm.getId());
                    }else {
                        exceptionUtil.logError(this.getClass(), "commentTmpMsg", resp.getMsg());
                    }

                }else {
                    exceptionUtil.logError(this.getClass(), "commentTmpMsg", "no formid " + toUser.getId());
                }
            }else {
                exceptionUtil.logError(this.getClass(), "commentTmpMsg", "toUser:" + toUser.getId() + " or fromUser:" + cUser.getId() + " not found");
            }
        }else {
            exceptionUtil.logError(this.getClass(), "commentTmpMsg", "has unread msg,skip!");
        }

        return ResponseV2.ok(cd);
    }

    private boolean isTimeForTmpMsg() {
        Calendar rightNow = Calendar.getInstance();
        int hour = rightNow.get(Calendar.HOUR_OF_DAY);
        return (hour > 8 && hour <23);
    }

    @Override
    public Comment getComment(Long owner, Long commenter) {
        return commentDao.findByOwnerAndCommenter(owner, commenter);
    }
}
